package upm.pb4agent.team3;

import jade.content.Concept;
import jade.content.ContentElement;
import jade.content.lang.Codec;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.content.onto.basic.Action;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.domain.DFService;
import jade.domain.FIPANames;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import jade.proto.SubscriptionInitiator;

import java.util.Vector;

import upm.pb4agent.ontology.PB4AgentOntology;
import upm.pb4agent.ontology.PickSeat;
import upm.pb4agent.ontology.RaceStarted;
import upm.pb4agent.ontology.Seat;
import upm.pb4agent.ontology.SubscribeReferee;


/**
 * This agent has the following functionality: 
 * <ul>
 * <li> 
 * <li> 
 * </ul>
 * @author Team3, UPM
 */
public class SubscriptionInitiatorToReferee extends CyclicBehaviour{
	private static final long serialVersionUID = 8850313898130957002L;
	private AID agRefereeAid = null;
	
	private Codec codec = new SLCodec();
	private Ontology ontology = PB4AgentOntology.getInstance();
	
	public SubscriptionInitiatorToReferee(Agent agent) {
        super(agent); 
        agRefereeAid = MyAgent.searchAgentInDF(super.myAgent,Constant.SD_REFEREE);
                
        prepareSubscriptions( new ACLMessage(ACLMessage.SUBSCRIBE));
    } 
	
	protected Vector<ACLMessage> prepareSubscriptions(ACLMessage subscription) {
		Vector<ACLMessage> v = null;
		try{
			if(agRefereeAid == null){
				agRefereeAid = MyAgent.searchAgentInDF(super.myAgent,Constant.SD_REFEREE);
			}else{	    	
				subscription.addReceiver(agRefereeAid);// the agent supplying a subscription service (has a responder role)
		        v = new Vector<ACLMessage>();
		        
		        subscription.setLanguage(codec.getName());
		        subscription.setOntology(ontology.getName());
		        subscription.setProtocol("SubscribeReferee");
		        
		        //--adding the respective action
		        Action agAction = new Action(agRefereeAid,new SubscribeReferee());
				super.myAgent.getContentManager().fillContent(subscription, agAction);		        
		        //--
				
		        v.addElement(subscription);
		        //System.out.println(myAgent.getLocalName() + ", enviando requerimiento de subscripcion: ");
		        
		        super.myAgent.send(subscription);
			}
			return v;
		}catch (Exception e) {
			System.out.println(myAgent.getLocalName() + ", error: "+ e.toString());
			return v;
		}
       
    }
	
	
	
	public void action() {
		
		ACLMessage aclMessage = super.myAgent.receive( MessageTemplate.and(
																		    MessageTemplate.and(			
																				   				 MessageTemplate.MatchLanguage(codec.getName())
																				   				,MessageTemplate.MatchOntology(ontology.getName())
																				   			   )
																			,MessageTemplate.MatchProtocol("RaceStarted")
																			)
														);			
		
		if(aclMessage == null){
			block();
		}else{
			switch(aclMessage.getPerformative()) {
				case ACLMessage.AGREE:
					handleAgree(aclMessage);
					break;
				case ACLMessage.INFORM:
					handleInform(aclMessage);
					break; 
				case ACLMessage.NOT_UNDERSTOOD:
					handleNotUnderstood(aclMessage);
					break; 
				case ACLMessage.REFUSE:
					handleRefuse(aclMessage);
					break; 
				case ACLMessage.CANCEL:
					cancelSubscriptions(aclMessage);
					break; 				
				default:
					break;
			}
		}
		
	}
	
	protected void handleAgree(ACLMessage agree) {
        // handle inform messages from the subscription service that
    	//was subscribed to
    	//System.out.println(myAgent.getLocalName() + ": AGREE <-- " + " I'm subscribed to: " + Constant.SD_REFEREE);
    	//cancel(agRefereeAid, false) ;
    }

    protected void handleInform(ACLMessage inform) {
        // handle inform messages from the subscription service that    
    	//System.out.println(myAgent.getLocalName() + ": handleInform <--" + inform);
    	try{
			ContentElement contentElement = super.myAgent.getContentManager().extractContent(inform);
			if (contentElement instanceof Action){
				Action action = (Action) contentElement;
				Concept concept = action.getAction();
				if(concept instanceof RaceStarted){
					String name = super.myAgent.getLocalName();					
					
					if(super.myAgent.getLocalName().equals(Constant.NAME_ROWER_1)
						/*|| super.myAgent.getLocalName().equals(Constant.NAME_ROWER_2)	
						|| super.myAgent.getLocalName().equals(Constant.NAME_ROWER_3)
						|| super.myAgent.getLocalName().equals(Constant.NAME_ROWER_4)	*/
							){
						//Send message to boat
						Seat seat = new Seat();
						seat.setSeatID(Constant.NAME_SEAT_5);
						PickSeat pickSeat = new PickSeat();
						pickSeat.setSeatID(seat);
						
						
						Rower row = (Rower)(super.myAgent);
						Action actionPickSeat = new Action(row.boatTeam.getID(), pickSeat);
						
						ACLMessage aclMessage = new ACLMessage(ACLMessage.INFORM);
	
						aclMessage.setLanguage(codec.getName());
						aclMessage.setOntology(ontology.getName());
						aclMessage.addReceiver(row.boatTeam.getID());
						aclMessage.setProtocol("PickSeat");
						
						super.myAgent.getContentManager().fillContent(aclMessage, actionPickSeat);
						
						
						super.myAgent.send(aclMessage);
					}
					//cancel(agRefereeAid, false) ;
					//cancelSubscriptions(new ACLMessage(ACLMessage.CANCEL));
				}
			}
		}catch (Exception e) {			
			System.out.println(myAgent.getLocalName() + ":"  + ", not understood");
		}
    	
    }
    
    protected void handleNotUnderstood(ACLMessage notUnderstood){
        // handle a refusal from the subscription service
    	System.out.println(myAgent.getLocalName() + ": NOT_UNDERSTOOD <--" + Constant.SD_REFEREE + " notUnderstood.");
    }
    
    protected void handleRefuse(ACLMessage refuse) {
        // handle a refusal from the subscription service
    }
    
    
    protected Vector<ACLMessage> cancelSubscriptions(ACLMessage cancelsubscription) {
		Vector<ACLMessage> v = null;
		try{	    		    
			if(agRefereeAid == null){
				agRefereeAid = MyAgent.searchAgentInDF(super.myAgent,Constant.SD_REFEREE);
			}else{				
				cancelsubscription.addReceiver(agRefereeAid);// the agent supplying a subscription service (has a responder role)
		        v = new Vector<ACLMessage>();
		        
		        //cancelsubscription.setProtocol(FIPANames.InteractionProtocol.FIPA_SUBSCRIBE);	
		        cancelsubscription.setLanguage(codec.getName());
		        cancelsubscription.setOntology(ontology.getName());
		        cancelsubscription.setPerformative(ACLMessage.CANCEL);
		        		        
		        v.addElement(cancelsubscription);
		        
		        super.myAgent.send(cancelsubscription);
		        //System.out.println(myAgent.getLocalName() + ", enviando requerimiento de unSubscripcion: ");
			}
			return v;
		}catch (Exception e) {
			System.out.println(myAgent.getLocalName() + ", error: "+ e.toString());
			return v;
		}
       
    }
} 